package com.xxl.job.admin.service.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.core.vo.XxlJobSumVo;
import com.xxl.job.admin.dao.XxlJobLogDao;
import com.xxl.job.admin.service.XxlJobLogService;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

import static com.mybatisflex.core.query.QueryMethods.*;
import static com.xxl.job.admin.core.model.table.Tables.XXL_JOB_LOG;
import static com.xxl.job.admin.core.model.table.Tables.XXL_JOB_REGISTRY;

@Service
public class XxlJobLogServiceImpl extends ServiceImpl<XxlJobLogDao, XxlJobLog> implements XxlJobLogService {

    @Override
    public List<Long> findClearLogIds(int jobGroup, int jobId, Date clearBeforeTime, int clearBeforeNum, int pagesize) {

        QueryWrapper q = QueryWrapper.create().select(XXL_JOB_LOG.ID)
                .where(XXL_JOB_LOG.JOB_GROUP.eq(jobGroup).when(jobGroup>0))
                .and(XXL_JOB_LOG.JOB_ID.eq(jobId).when(jobId>0))
                .and(XXL_JOB_LOG.TRIGGER_TIME.le(clearBeforeTime))
                .and(XXL_JOB_LOG.ID.notIn(new QueryWrapper()
                        .select(XXL_JOB_LOG.ID).from(new QueryWrapper()
                                        .select(XXL_JOB_LOG.ID).from(XXL_JOB_LOG)
                                        .where(XXL_JOB_LOG.JOB_GROUP.eq(jobGroup).when(jobGroup>0))
                                        .and(XXL_JOB_LOG.JOB_ID.eq(jobId).when(jobId>0))
                                        .orderBy(XXL_JOB_LOG.TRIGGER_TIME.desc())
                                        .limit(0,clearBeforeNum)
                                ).as("t1")
                )
                )
                .orderBy(XXL_JOB_LOG.ID.asc())
                .limit(pagesize);

        return listAs(q,Long.class);
    }

    @Override
    public void clearLog(List<Long> logIds) {
        removeByIds(logIds);
    }


    @Override
    public Page<XxlJobLog> pageList(int start, int length, int jobGroup, int jobId, Date triggerTimeStart, Date triggerTimeEnd, int logStatus) {
        QueryWrapper queryWrapper = QueryWrapper.create().
                from(XXL_JOB_LOG)
                .where(XXL_JOB_LOG.JOB_GROUP.eq(jobGroup).when(jobId==0&&jobGroup>0))
                .and(XXL_JOB_LOG.JOB_ID.eq(jobId).when(jobId>0))
                .and(XXL_JOB_LOG.TRIGGER_TIME.ge(triggerTimeStart).when(triggerTimeStart !=null))
                .and(XXL_JOB_LOG.TRIGGER_TIME.le(triggerTimeEnd).when(triggerTimeEnd !=null))
                .and(XXL_JOB_LOG.HANDLE_CODE.eq(200).when(logStatus ==1))
                .and((XXL_JOB_LOG.TRIGGER_CODE.notIn(0,200).when(logStatus==2)
                        .or(XXL_JOB_LOG.HANDLE_CODE.notIn(0,200).when(logStatus==2))))
                .and(XXL_JOB_LOG.HANDLE_CODE.eq(0).when(logStatus==3))
                .and(XXL_JOB_LOG.TRIGGER_CODE.eq(200).when(logStatus==3))
                .orderBy(XXL_JOB_LOG.TRIGGER_TIME.desc());
        Page<XxlJobLog> xxlJobLogPage = mapper.paginate(start,length,queryWrapper);
        return xxlJobLogPage;
    }

    @Override
    public XxlJobSumVo findLogReport(Date todayFrom, Date todayTo) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(QueryMethods.count(XXL_JOB_LOG.HANDLE_CODE).as("triggerDayCount"),
                        sum(case_()
                                .when(XXL_JOB_LOG.TRIGGER_CODE.in(0,200).and(XXL_JOB_LOG.HANDLE_CODE.eq(0)))
                                .then(1)
                                .else_(0)
                                .end())
                                .as("triggerDayCountRunning"),
                        sum(case_().when(XXL_JOB_LOG.TRIGGER_CODE.eq(200)).then(1).else_(0).end())
                                .as("triggerDayCountSuc")
                )
                .from(XXL_JOB_LOG)
                .where(XXL_JOB_LOG.TRIGGER_TIME.between(todayFrom,todayTo));
        return getOneAs(queryWrapper,XxlJobSumVo.class);
    }

    @Override
    public List<Long> findLostJobIds(Date losedTime) {
        QueryWrapper queryWrapper = QueryWrapper.create().select(XXL_JOB_LOG.ID)
                .from(XXL_JOB_LOG).leftJoin(XXL_JOB_REGISTRY).on(XXL_JOB_LOG.EXECUTOR_ADDRESS.eq(XXL_JOB_REGISTRY.REGISTRY_VALUE))
                .where(XXL_JOB_LOG.TRIGGER_CODE.eq(200))
                .and(XXL_JOB_LOG.HANDLE_CODE.eq(0))
                .and(XXL_JOB_LOG.TRIGGER_TIME.le(losedTime))
                .and(XXL_JOB_LOG.ID.isNull());
        return listAs(queryWrapper,Long.class);
    }
    @Override
    public List<Long> findFailJobLogIds(int i) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(XXL_JOB_LOG.ID)
                .from(XXL_JOB_LOG)
//                .where((XXL_JOB_LOG.TRIGGER_CODE.notIn(0,200).and(XXL_JOB_LOG.HANDLE_CODE.ne(0)))).or((XXL_JOB_LOG.HANDLE_CODE.ne(200)))
                .where(not((XXL_JOB_LOG.TRIGGER_CODE.in(0,200).and(XXL_JOB_LOG.HANDLE_CODE.eq(0))).or(XXL_JOB_LOG.HANDLE_CODE.eq(200))))
                .and(XXL_JOB_LOG.ALARM_STATUS.eq(0))
                .orderBy(XXL_JOB_LOG.ID.asc())
                .limit(i);
        return listAs(queryWrapper,Long.class);
    }


//    <update id="updateAlarmStatus" >
//    UPDATE xxl_job_log
//    SET
//			`alarm_status` = #{newAlarmStatus}
//    WHERE `id`= #{logId} AND `alarm_status` = #{oldAlarmStatus}
//	</update>

    @Override
    public int updateAlarmStatus(long logId, int oldAlarmStatus, int newAlarmStatus) {
      boolean i=  UpdateChain.of(XxlJobLog.class)
                .set(XXL_JOB_LOG.ALARM_STATUS,newAlarmStatus)
                .where(XXL_JOB_LOG.ID.eq(logId))
                .and(XXL_JOB_LOG.ALARM_STATUS.eq(oldAlarmStatus)).update();
        return i?1:0;
    }

    @Override
    public void removeByJobId(int id) {
        remove(XXL_JOB_LOG.JOB_ID.eq(id));
    }
}
